package com.sophialex.health.record.common.bind.model;

import java.lang.reflect.Method;

import net.sf.cglib.proxy.MethodInterceptor;
import net.sf.cglib.proxy.MethodProxy;

import com.sophia.pojo.AbstractModelObject;
/**
 * @author sunxq
 * 此类拦截领域类的方法调用，为setter触发属性改变事件
 */
public class BeanInterceptor implements MethodInterceptor {
	private boolean isDebug = true;
	public BeanInterceptor() {
		
	}
	public BeanInterceptor(boolean isDebug) {
		this.isDebug = isDebug;
	}
	public void print(String s){
		if(isDebug)
			System.out.print(s);
	}
	public void println(String s){
		if(isDebug)
			System.out.println(s);
	}
	public Object intercept(Object obj, Method method, Object[] args, MethodProxy proxy) throws Throwable {
		
		if(method.getName().startsWith("set")){
			print("拦截到 "+obj.getClass().getSimpleName()+"."+method.getName()+"(");
			for(Object ao:args){
				print(ao+"");
			}
			println(")");
			if(args == null || args.length !=1){
				throw new RuntimeException("setter有且只能有一个参数！");
			}
		
			if(!AbstractModelObject.class.isAssignableFrom(obj.getClass()))
				throw new IllegalArgumentException("领域类 "+obj.getClass().getSimpleName()+" 必须继承AbstractModelObject!");
			//通过得到getXX()来取得旧值
			//println("g"+method.getName().substring(1));
			
			Method getter = null;
			try{
			getter = obj.getClass().getDeclaredMethod("g"+method.getName().substring(1));
			}catch(NoSuchMethodException e){
				getter = obj.getClass().getDeclaredMethod("is"+method.getName().substring(3));
			}
			//MethodProxy.
			Object oldValue = getter.invoke(obj);
			
			//调 用bean的setter
			Object o = proxy.invokeSuper(obj, args);
			
			
			
			
			//得到属性名
			String prop = method.getName().substring(3);
			prop = Character.toLowerCase(prop.charAt(0))+prop.substring(1);
			
			Object newValue = args[0];
		
			//调用firePropertyChange()方法,触发属性改变
//			Method m = obj.getClass().getDeclaredMethod("firePropertyChange", String.class, Object.class, Object.class);
//			m.invoke(obj, prop, null,newValue);
			AbstractModelObject mo = (AbstractModelObject)obj;
			//mo.firePropertyChange(prop, null, newValue);

			mo.firePropertyChange(prop, oldValue, newValue);
			return o;
			
		}
		return proxy.invokeSuper(obj, args);
	}

}

